<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Golang语言编码规范 | anyang的博客</title>
    <meta name="description" content="千里之行,始于足下">
    <meta name="generator" content="VuePress 1.3.1">
    <link rel="icon" href="/img/favicon.ico">
  <script charset="utf-8" src="/js/main.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.2/jquery.fancybox.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.2/jquery.fancybox.min.css">
  <meta name="keywords" content="福小林,奔奔,ourLang,CentOS,JAVA,vue组件,lsdCloud">
  <script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-146891701-1"></script>
  <script>window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
    
      gtag('config', 'UA-146891701-1');</script>
  <script>var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?56eae8eec590ccaef1d5ff99d766f315";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })();</script>
    
    <link rel="preload" href="/assets/css/0.styles.9fff9873.css" as="style"><link rel="preload" href="/assets/js/app.1bc80adb.js" as="script"><link rel="preload" href="/assets/js/2.7c0608ab.js" as="script"><link rel="preload" href="/assets/js/88.e564cbbe.js" as="script"><link rel="prefetch" href="/assets/js/10.81caa2ab.js"><link rel="prefetch" href="/assets/js/100.05bb269d.js"><link rel="prefetch" href="/assets/js/101.3e18b4d6.js"><link rel="prefetch" href="/assets/js/102.c7d7ed9c.js"><link rel="prefetch" href="/assets/js/103.4c771ce7.js"><link rel="prefetch" href="/assets/js/104.a2acd367.js"><link rel="prefetch" href="/assets/js/105.63399350.js"><link rel="prefetch" href="/assets/js/106.8a4744cc.js"><link rel="prefetch" href="/assets/js/107.7739d796.js"><link rel="prefetch" href="/assets/js/108.8008ae33.js"><link rel="prefetch" href="/assets/js/109.01c63898.js"><link rel="prefetch" href="/assets/js/11.7b837560.js"><link rel="prefetch" href="/assets/js/110.ad01aca9.js"><link rel="prefetch" href="/assets/js/111.3d74db70.js"><link rel="prefetch" href="/assets/js/112.67f55c34.js"><link rel="prefetch" href="/assets/js/113.016cd3c0.js"><link rel="prefetch" href="/assets/js/114.860e4b2b.js"><link rel="prefetch" href="/assets/js/115.b2f26258.js"><link rel="prefetch" href="/assets/js/116.8bea67b4.js"><link rel="prefetch" href="/assets/js/117.20682843.js"><link rel="prefetch" href="/assets/js/118.86a22e16.js"><link rel="prefetch" href="/assets/js/119.ad518bea.js"><link rel="prefetch" href="/assets/js/12.8fd78714.js"><link rel="prefetch" href="/assets/js/120.f97dd86f.js"><link rel="prefetch" href="/assets/js/121.c5601b4a.js"><link rel="prefetch" href="/assets/js/122.2889645a.js"><link rel="prefetch" href="/assets/js/13.ebf26820.js"><link rel="prefetch" href="/assets/js/14.b92dca09.js"><link rel="prefetch" href="/assets/js/15.b3dcef45.js"><link rel="prefetch" href="/assets/js/16.50378990.js"><link rel="prefetch" href="/assets/js/17.056bba2b.js"><link rel="prefetch" href="/assets/js/18.9047bb38.js"><link rel="prefetch" href="/assets/js/19.ab53b0fe.js"><link rel="prefetch" href="/assets/js/20.fe0b8af0.js"><link rel="prefetch" href="/assets/js/21.20a702f3.js"><link rel="prefetch" href="/assets/js/22.0ee08d29.js"><link rel="prefetch" href="/assets/js/23.02039a9a.js"><link rel="prefetch" href="/assets/js/24.363d3d74.js"><link rel="prefetch" href="/assets/js/25.dd6b101e.js"><link rel="prefetch" href="/assets/js/26.20493714.js"><link rel="prefetch" href="/assets/js/27.708723e5.js"><link rel="prefetch" href="/assets/js/28.4561834a.js"><link rel="prefetch" href="/assets/js/29.15cfcf5f.js"><link rel="prefetch" href="/assets/js/3.8d39d40c.js"><link rel="prefetch" href="/assets/js/30.04ab69de.js"><link rel="prefetch" href="/assets/js/31.b11c4302.js"><link rel="prefetch" href="/assets/js/32.81ae74ee.js"><link rel="prefetch" href="/assets/js/33.ddf09cc0.js"><link rel="prefetch" href="/assets/js/34.bc3549f7.js"><link rel="prefetch" href="/assets/js/35.4a0e0ebd.js"><link rel="prefetch" href="/assets/js/36.961a1c50.js"><link rel="prefetch" href="/assets/js/37.d8658de5.js"><link rel="prefetch" href="/assets/js/38.f76063aa.js"><link rel="prefetch" href="/assets/js/39.73edd08f.js"><link rel="prefetch" href="/assets/js/4.916af9bf.js"><link rel="prefetch" href="/assets/js/40.72314bff.js"><link rel="prefetch" href="/assets/js/41.c5eb1147.js"><link rel="prefetch" href="/assets/js/42.07aeafbb.js"><link rel="prefetch" href="/assets/js/43.c4a652ba.js"><link rel="prefetch" href="/assets/js/44.91fbe22b.js"><link rel="prefetch" href="/assets/js/45.6eecf0c4.js"><link rel="prefetch" href="/assets/js/46.81b7f108.js"><link rel="prefetch" href="/assets/js/47.b4468ab3.js"><link rel="prefetch" href="/assets/js/48.df205f23.js"><link rel="prefetch" href="/assets/js/49.7df59fa3.js"><link rel="prefetch" href="/assets/js/5.4fcd540a.js"><link rel="prefetch" href="/assets/js/50.0dc2fc5b.js"><link rel="prefetch" href="/assets/js/51.1ffabe54.js"><link rel="prefetch" href="/assets/js/52.2269d284.js"><link rel="prefetch" href="/assets/js/53.81b23843.js"><link rel="prefetch" href="/assets/js/54.b3249def.js"><link rel="prefetch" href="/assets/js/55.50dcf2af.js"><link rel="prefetch" href="/assets/js/56.c399c272.js"><link rel="prefetch" href="/assets/js/57.024f1dbb.js"><link rel="prefetch" href="/assets/js/58.680c6cf4.js"><link rel="prefetch" href="/assets/js/59.2291e9d7.js"><link rel="prefetch" href="/assets/js/6.7610d1d4.js"><link rel="prefetch" href="/assets/js/60.e59a26c1.js"><link rel="prefetch" href="/assets/js/61.ff5c64e4.js"><link rel="prefetch" href="/assets/js/62.7d97062c.js"><link rel="prefetch" href="/assets/js/63.6456dc7e.js"><link rel="prefetch" href="/assets/js/64.0b055680.js"><link rel="prefetch" href="/assets/js/65.9f25601c.js"><link rel="prefetch" href="/assets/js/66.cd973084.js"><link rel="prefetch" href="/assets/js/67.9b8f9716.js"><link rel="prefetch" href="/assets/js/68.d6c1869a.js"><link rel="prefetch" href="/assets/js/69.0a3688dd.js"><link rel="prefetch" href="/assets/js/7.9ebbd956.js"><link rel="prefetch" href="/assets/js/70.22f48891.js"><link rel="prefetch" href="/assets/js/71.9eb4fda9.js"><link rel="prefetch" href="/assets/js/72.ca4fa80c.js"><link rel="prefetch" href="/assets/js/73.17d1ab37.js"><link rel="prefetch" href="/assets/js/74.139691db.js"><link rel="prefetch" href="/assets/js/75.08d0560f.js"><link rel="prefetch" href="/assets/js/76.61078c10.js"><link rel="prefetch" href="/assets/js/77.4482adcc.js"><link rel="prefetch" href="/assets/js/78.166f2c37.js"><link rel="prefetch" href="/assets/js/79.2c7d6b79.js"><link rel="prefetch" href="/assets/js/8.6f8916c2.js"><link rel="prefetch" href="/assets/js/80.80445c3f.js"><link rel="prefetch" href="/assets/js/81.14e3bae8.js"><link rel="prefetch" href="/assets/js/82.7dac687f.js"><link rel="prefetch" href="/assets/js/83.1dd2e78e.js"><link rel="prefetch" href="/assets/js/84.23b759de.js"><link rel="prefetch" href="/assets/js/85.7574f69f.js"><link rel="prefetch" href="/assets/js/86.102dac61.js"><link rel="prefetch" href="/assets/js/87.8f5d639e.js"><link rel="prefetch" href="/assets/js/89.cd66eb78.js"><link rel="prefetch" href="/assets/js/9.baa162db.js"><link rel="prefetch" href="/assets/js/90.685c6878.js"><link rel="prefetch" href="/assets/js/91.b8d1b7ea.js"><link rel="prefetch" href="/assets/js/92.1faa374d.js"><link rel="prefetch" href="/assets/js/93.cf5ff33c.js"><link rel="prefetch" href="/assets/js/94.8a02aefb.js"><link rel="prefetch" href="/assets/js/95.1b379a5b.js"><link rel="prefetch" href="/assets/js/96.9fd67185.js"><link rel="prefetch" href="/assets/js/97.c5a6a5a1.js"><link rel="prefetch" href="/assets/js/98.9a231411.js"><link rel="prefetch" href="/assets/js/99.5b344cab.js">
    <link rel="stylesheet" href="/assets/css/0.styles.9fff9873.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">anyang的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">
  主页
</a></div><div class="nav-item"><a href="/study-guide/introduction.html" class="nav-link">
  学习指南
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="技术分类" class="dropdown-title"><span class="title">技术分类</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/java/introduction.html" class="nav-link">
  Java
</a></li><li class="dropdown-item"><!----> <a href="/go/introduction.html" class="nav-link">
  Go
</a></li><li class="dropdown-item"><!----> <a href="/sql/introduction.html" class="nav-link">
  SQL
</a></li><li class="dropdown-item"><!----> <a href="/fhir/introduction.html" class="nav-link">
  FHIR
</a></li></ul></div></div><div class="nav-item"><a href="/blog/introduction.html" class="nav-link">
  个人博客
</a></div><div class="nav-item"><a href="/tool/developmentBox.html" class="nav-link">
  开发百宝箱
</a></div><div class="nav-item"><a href="/project/introduction.html" class="nav-link">
  项目分享
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="了解更多" class="dropdown-title"><span class="title">了解更多</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="http://wpa.qq.com/msgrd?v=3&amp;uin=1300378587&amp;site=qq&amp;menu=yes" target="_blank" rel="noopener noreferrer" class="nav-link external">
  其他合作
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="http://www.lsdcloud.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  友情网站
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://github.com/ourlang" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/anlexanyang" target="_blank" rel="noopener noreferrer" class="nav-link external">
  码云
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://blog.csdn.net/qq_37493556" target="_blank" rel="noopener noreferrer" class="nav-link external">
  CSDN
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></div></div><div class="nav-item"><a href="/linkExchanges/introduction.html" class="nav-link">
  友情链接
</a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">
  主页
</a></div><div class="nav-item"><a href="/study-guide/introduction.html" class="nav-link">
  学习指南
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="技术分类" class="dropdown-title"><span class="title">技术分类</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/java/introduction.html" class="nav-link">
  Java
</a></li><li class="dropdown-item"><!----> <a href="/go/introduction.html" class="nav-link">
  Go
</a></li><li class="dropdown-item"><!----> <a href="/sql/introduction.html" class="nav-link">
  SQL
</a></li><li class="dropdown-item"><!----> <a href="/fhir/introduction.html" class="nav-link">
  FHIR
</a></li></ul></div></div><div class="nav-item"><a href="/blog/introduction.html" class="nav-link">
  个人博客
</a></div><div class="nav-item"><a href="/tool/developmentBox.html" class="nav-link">
  开发百宝箱
</a></div><div class="nav-item"><a href="/project/introduction.html" class="nav-link">
  项目分享
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="了解更多" class="dropdown-title"><span class="title">了解更多</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="http://wpa.qq.com/msgrd?v=3&amp;uin=1300378587&amp;site=qq&amp;menu=yes" target="_blank" rel="noopener noreferrer" class="nav-link external">
  其他合作
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="http://www.lsdcloud.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  友情网站
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://github.com/ourlang" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/anlexanyang" target="_blank" rel="noopener noreferrer" class="nav-link external">
  码云
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://blog.csdn.net/qq_37493556" target="_blank" rel="noopener noreferrer" class="nav-link external">
  CSDN
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></div></div><div class="nav-item"><a href="/linkExchanges/introduction.html" class="nav-link">
  友情链接
</a></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/go/introduction.html" class="sidebar-link">Go语言</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Go教程</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Go Web框架</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Go工具中间件</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/go/middleware/go-coding-standard.html" class="active sidebar-link">Golang语言编码规范</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#前言" class="sidebar-link">前言</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-命名规范" class="sidebar-link">1 命名规范</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-1-文件名" class="sidebar-link">1.1 文件名</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-2-包命名" class="sidebar-link">1.2 包命名</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-3-结构体命名" class="sidebar-link">1.3 结构体命名</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-4-接口名" class="sidebar-link">1.4 接口名</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-5-函数命名" class="sidebar-link">1.5 函数命名</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-6-常量命名" class="sidebar-link">1.6 常量命名</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_1-7-变量命名" class="sidebar-link">1.7 变量命名</a></li></ul></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-注释规范" class="sidebar-link">2 注释规范</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-1-包注释" class="sidebar-link">2.1 包注释</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-2-结构体-接口-注释" class="sidebar-link">2.2 结构体 (接口) 注释</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-3-函数（方法）注释" class="sidebar-link">2.3 函数（方法）注释</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-4-代码逻辑注释" class="sidebar-link">2.4 代码逻辑注释</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-5-bug注释" class="sidebar-link">2.5 bug注释</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_2-6-注释风格" class="sidebar-link">2.6 注释风格</a></li></ul></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-代码风格" class="sidebar-link">3 代码风格</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-1-缩进和折行" class="sidebar-link">3.1  缩进和折行</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-2-控制结构" class="sidebar-link">3.2 控制结构</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-3-结构体和接口" class="sidebar-link">3.3 结构体和接口</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-4-接收者" class="sidebar-link">3.4 接收者</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-5-defer" class="sidebar-link">3.5 defer</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-5-chan" class="sidebar-link">3.5 chan</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-6-goroutine" class="sidebar-link">3.6 goroutine</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-7-import-规范" class="sidebar-link">3.7 import 规范</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-8-错误处理" class="sidebar-link">3.8 错误处理</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-9-参数传递" class="sidebar-link">3.9 参数传递</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_3-10-单元测试" class="sidebar-link">3.10 单元测试</a></li></ul></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_4-数据库规范" class="sidebar-link">4 数据库规范</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_4-1-总命名规范" class="sidebar-link">4.1 总命名规范</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_4-2-建表规范" class="sidebar-link">4.2 建表规范</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_4-3-索引规约" class="sidebar-link">4.3 索引规约</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_4-4-sql规约" class="sidebar-link">4.4 SQL规约</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_4-5-orm规约" class="sidebar-link">4.5 ORM规约</a></li></ul></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_5-项目开发规范" class="sidebar-link">5 项目开发规范</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_5-1-项目目录结构" class="sidebar-link">5.1 项目目录结构</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_5-2-包管理器" class="sidebar-link">5.2 包管理器</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_5-3-自动格式化" class="sidebar-link">5.3 自动格式化</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_5-4-常用中间件" class="sidebar-link">5.4 常用中间件</a></li></ul></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_6-安全规约" class="sidebar-link">6 安全规约</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_6-1-权限控制校验" class="sidebar-link">6.1 权限控制校验</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_6-2-数据脱敏" class="sidebar-link">6.2 数据脱敏</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_6-3-防止sql注入" class="sidebar-link">6.3 防止SQL注入</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_6-4-参数有效性验证" class="sidebar-link">6.4 参数有效性验证</a></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_6-5-csrf安全过滤" class="sidebar-link">6.5 CSRF安全过滤</a></li></ul></li><li class="sidebar-sub-header"><a href="/go/middleware/go-coding-standard.html#_7-参考资料" class="sidebar-link">7 参考资料</a></li></ul></li><li><a href="/go/middleware/go-get命令详解.html" class="sidebar-link">go get命令详解</a></li><li><a href="/go/middleware/go-mysql.html" class="sidebar-link">Go语言操作Mysql</a></li><li><a href="/go/middleware/go-redis.html" class="sidebar-link">go-redis文档</a></li><li><a href="/go/middleware/go-swagger.html" class="sidebar-link">go-swagger安装及使用</a></li><li><a href="/go/middleware/go-viper.html" class="sidebar-link">viper操作文档</a></li><li><a href="/go/middleware/Goland的自定义快捷键配置.html" class="sidebar-link">配置Goland的自定义快捷键</a></li><li><a href="/go/middleware/Golang的安装配置golint.html" class="sidebar-link">Golang的安装配置golint</a></li><li><a href="/go/middleware/goproxy.html" class="sidebar-link">GoLand配置GOPROXY代理</a></li><li><a href="/go/middleware/gorm.html" class="sidebar-link">GORM基本操作</a></li><li><a href="/go/middleware/json-iterator.html" class="sidebar-link">json-iterator使用</a></li><li><a href="/go/middleware/package.html" class="sidebar-link">Go语言包和包管理</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="golang语言编码规范"><a href="#golang语言编码规范" class="header-anchor">#</a> Golang语言编码规范</h1> <p><a data-fancybox="" title="go-coding" href="/img/goImage/go-coding.png"><img src="/img/goImage/go-coding.png" alt="go-coding"></a></p> <table><thead><tr><th>版本号</th> <th>编写团队</th> <th>更新日期</th> <th>备注</th></tr></thead> <tbody><tr><td>1.0</td> <td>成都新生泰技术团队</td> <td>2020.2.10</td> <td>正式版</td></tr></tbody></table> <h2 id="前言"><a href="#前言" class="header-anchor">#</a> 前言</h2> <blockquote><p>这是一份关于Go语言开发的参考手册。欲获取更多信息与文档，请访问<a href="http://golang.org/" target="_blank" rel="noopener noreferrer">http://golang.org<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p></blockquote> <h2 id="_1-命名规范"><a href="#_1-命名规范" class="header-anchor">#</a> 1 命名规范</h2> <p>命名是代码规范中很重要的一部分,统一的命名规则有利于提高的代码的可读性,好的命名仅仅通过命名就可以获取到足够多的信息。</p> <p>Go在命名时以字母<code>a到Z或a到Z</code>或下划线开头,后面跟着零或更多的字母、下划线和数字<code>(0到9)</code>。Go不允许在命名时中使用<code>@、$和%</code>等标点符号。Go是一种区分大小写的编程语言。因此，<code>Manpower</code>和<code>manpower</code>是两个不同的命名。</p> <ul><li>1 当命名(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如：<code>Group1</code>,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 <code>public</code>)</li> <li>2 命名如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的<code>private</code>)</li></ul> <h3 id="_1-1-文件名"><a href="#_1-1-文件名" class="header-anchor">#</a> 1.1 文件名</h3> <p>尽量采取有意义的文件名，简短，有意义，应该为<strong>小写</strong>单词，使用<strong>下划线</strong>分隔各个单词。</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code>my_test<span class="token punctuation">.</span><span class="token keyword">go</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h3 id="_1-2-包命名"><a href="#_1-2-包命名" class="header-anchor">#</a> 1.2 包命名</h3> <blockquote><p>保持package的名字和目录保持一致，尽量采取有意义的包名，简短，有意义，尽量和标准库不要冲突。包名应该为<strong>小写</strong>单词，不要使用下划线或者混合大小写。</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> demo

<span class="token keyword">package</span> main

<span class="token keyword">package</span> utils
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_1-3-结构体命名"><a href="#_1-3-结构体命名" class="header-anchor">#</a> 1.3 结构体命名</h3> <ul><li><p>采用驼峰命名法，首字母根据访问控制大写或者小写</p></li> <li><p><code>struct</code>申明和初始化格式采用多行，例如下面：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// 多行申明</span>
<span class="token keyword">type</span> User <span class="token keyword">struct</span><span class="token punctuation">{</span>
    UserName  <span class="token builtin">string</span>
    Email     <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token comment">// 多行初始化</span>
u <span class="token operator">:=</span> User<span class="token punctuation">{</span>
    UserName<span class="token punctuation">:</span> <span class="token string">&quot;astaxie&quot;</span><span class="token punctuation">,</span>
    Email<span class="token punctuation">:</span>    <span class="token string">&quot;astaxie@gmail.com&quot;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div></li></ul> <h3 id="_1-4-接口名"><a href="#_1-4-接口名" class="header-anchor">#</a> 1.4 接口名</h3> <ul><li>命名规则基本和上面的结构体类型</li> <li>单个函数的结构名以 “er” 作为后缀，例如 <code>Reader , Writer</code>。</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> Reader <span class="token keyword">interface</span> <span class="token punctuation">{</span>
        <span class="token function">Read</span><span class="token punctuation">(</span>p <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>n <span class="token builtin">int</span><span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><ul><li><p>两个函数的接口名综合两个函数名</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> WriteFlusher <span class="token keyword">interface</span> <span class="token punctuation">{</span>
    <span class="token function">Write</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span>
    <span class="token function">Flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></li> <li><p>三个以上函数的接口名，类似于结构体名</p></li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> Car <span class="token keyword">interface</span> <span class="token punctuation">{</span>
    <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span>
    <span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span>
    <span class="token function">Recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_1-5-函数命名"><a href="#_1-5-函数命名" class="header-anchor">#</a> 1.5 函数命名</h3> <blockquote><p>若函数或方法为判断类型（返回值主要为 <code>bool</code> 类型），则名称应以 <code>Has</code>, <code>Is</code>, <code>Can</code> 或 <code>Allow</code> 等判断性动词开头：</p></blockquote> <div class="language-gO line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">HasPrefix</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> prefixes <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">IsEntry</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> entries <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">CanManage</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">AllowGitHook</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h3 id="_1-6-常量命名"><a href="#_1-6-常量命名" class="header-anchor">#</a> 1.6 常量命名</h3> <blockquote><p>常量包含(布尔常量、符文常量、整数常量、浮点数常量、复数常量和字符串常量)。字符、整数、浮点数和复数常量统称为<strong>数值常量</strong>。</p></blockquote> <ul><li>常量均需使用全部大写字母组成，并使用下划线分词：const APP_VER = “1.0”</li> <li>如果是枚举类型的常量，需要先创建相应类型：</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> Scheme <span class="token builtin">string</span>
<span class="token keyword">const</span> <span class="token punctuation">(</span>
    HTTP  Scheme <span class="token operator">=</span> <span class="token string">&quot;http&quot;</span>
    HTTPS Scheme <span class="token operator">=</span> <span class="token string">&quot;https&quot;</span>
<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><ul><li>如果模块的功能较为复杂、常量名称容易混淆的情况下,为了更好地区分枚举类型,可以使用完整的前缀：</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> PullRequestStatus <span class="token builtin">int</span>
<span class="token keyword">const</span> <span class="token punctuation">(</span>
    PULL_REQUEST_STATUS_CONFLICT PullRequestStatus <span class="token operator">=</span> <span class="token boolean">iota</span>
    PULL_REQUEST_STATUS_CHECKING
    PULL_REQUEST_STATUS_MERGEABLE
<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="_1-7-变量命名"><a href="#_1-7-变量命名" class="header-anchor">#</a> 1.7 变量命名</h3> <blockquote><p>驼峰命名式。局部变量用小写字母开头。需要在<code>package</code>外部使用的全局变量用大写字母开头，否则用小写字母开头。</p></blockquote> <ul><li>全局变量:采用驼峰命名方式,仅限在包内的全局变量</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code>  <span class="token keyword">var</span> ProjectName <span class="token builtin">string</span> 
  <span class="token comment">//如多组变量则使用,组和声明或者平行赋值</span>
  <span class="token keyword">var</span><span class="token punctuation">(</span>
      ProjectName <span class="token builtin">string</span> 
   <span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><ul><li>局部变量:采用小驼峰命名方式,注意声明局部变量尽量使用 :=</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code>    projectName <span class="token operator">:=</span> <span class="token string">&quot;name&quot;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>在相对简单的环境（对象数量少、针对性强）中,可以将一些名称由完整单词简写为单个字母，例如：</p> <ul><li>user 可以简写为 u</li> <li>userID 可以简写 uid</li> <li>若变量类型为 bool 类型，则名称应以 Has, Is, Can 或 Allow 开头：</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">var</span> isExist <span class="token builtin">bool</span>
<span class="token keyword">var</span> hasConflict <span class="token builtin">bool</span>
<span class="token keyword">var</span> canManage <span class="token builtin">bool</span>
<span class="token keyword">var</span> allowGitHook <span class="token builtin">bool</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h2 id="_2-注释规范"><a href="#_2-注释规范" class="header-anchor">#</a> 2 注释规范</h2> <blockquote><p>Go提供C风格的<code>/* */</code>块注释和C ++风格的<code>//</code>行注释。行注释是常态；块注释主要显示为包注释，但在表达式中很有用或禁用大量代码。</p> <ul><li>单行注释是最常见的注释形式，你可以在任何地方使用以 // 开头的单行注释</li> <li>多行注释也叫块注释，均已以 /* 开头，并以 */ 结尾，且不可以嵌套使用，多行注释一般用于包的文档描述或注释成块的代码片段</li></ul></blockquote> <h3 id="_2-1-包注释"><a href="#_2-1-包注释" class="header-anchor">#</a> 2.1 包注释</h3> <blockquote><p>每个包都应该有一个包注释，一个位于<code>package</code>子句之前的块注释或行注释。包如果有多个go文件，只需要出现在一个go文件中（一般是和包同名的文件）即可。 包注释应该包含下面基本信息(请严格按照这个顺序，简介，创建人，创建时间）：</p> <ul><li>包的基本简介（包名，简介）</li> <li>创建者，格式： 创建人： rtx 名</li> <li>创建时间，格式：创建时间： yyyyMMdd</li></ul></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// util 包， 该包包含了项目共用的一些常量，封装了项目中一些共用函数。</span>
<span class="token comment">// 创建人： hanru</span>
<span class="token comment">// 创建时间： 20190419</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h3 id="_2-2-结构体-接口-注释"><a href="#_2-2-结构体-接口-注释" class="header-anchor">#</a> 2.2 结构体 (接口) 注释</h3> <blockquote><p>每个自定义的结构体或者接口都应该有注释说明，该注释对结构进行简要介绍，放在结构体定义的前一行，格式为： 结构体名， 结构体说明。同时结构体内的每个成员变量都要有说明，该说明放在成员变量的后面（注意对齐），实例如下：</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// User ， 用户对象，定义了用户的基础信息</span>
<span class="token keyword">type</span> User <span class="token keyword">struct</span><span class="token punctuation">{</span>
    Username  <span class="token builtin">string</span> <span class="token comment">// 用户名</span>
    Email     <span class="token builtin">string</span> <span class="token comment">// 邮箱</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_2-3-函数（方法）注释"><a href="#_2-3-函数（方法）注释" class="header-anchor">#</a> 2.3 函数（方法）注释</h3> <blockquote><p>每个函数，或者方法（结构体或者接口下的函数称为方法）都应该有注释说明。</p></blockquote> <h4 id="_2-3-1-函数注释"><a href="#_2-3-1-函数注释" class="header-anchor">#</a> 2.3.1 函数注释</h4> <blockquote><p>// @Title 标题</p> <p>// @Description 详细信息</p> <p>// @Auth 创建时间 创建人</p> <p>// @Param 参数类型 参数介绍</p> <p>// @Return 返回类型 &quot;错误信息&quot;</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// @Title NewtAttrModel </span>
<span class="token comment">// @Description 属性数据层操作类的工厂方法</span>
<span class="token comment">// @Auth 福小林</span>
<span class="token comment">// @Param  ctx  上下文信息</span>
<span class="token comment">// @Return 属性操作类指针</span>
<span class="token keyword">func</span> <span class="token function">NewAttrModel</span><span class="token punctuation">(</span>ctx <span class="token operator">*</span>common<span class="token punctuation">.</span>Context<span class="token punctuation">)</span> <span class="token operator">*</span>AttrModel <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h4 id="_2-3-2-函数注释"><a href="#_2-3-2-函数注释" class="header-anchor">#</a> 2.3.2 函数注释</h4> <blockquote><p>@Title  这个 API 所表达的含义，是一个文本，空格之后的内容全部解析为 title</p> <p>@Description 这个 API 详细的描述，是一个文本，空格之后的内容全部解析为 Description</p> <p>@Param  参数，表示需要传递到服务器端的参数,有五列参数,使用空格或者 tab 分割,表示的含义如下</p> <p>1 参数名</p> <p>2 参数类型，可以有的值是 formData、query、path、body、header，</p> <p>3 参数类型</p> <p>4 是否必须</p> <p>5 注释</p> <p>@Success  成功返回给客户端的信息</p> <p>@Failure  失败返回的信息，包含两个参数，使用空格分隔，第一个表示 status code，第二个表示错误信息</p> <p>@router  路由信息，包含两个参数，使用空格分隔，第一个是请求的路由地址，支持正则和自定义路由，和之前的路由规则一样，第二个参数是支持的请求方法,放在 [] 之中，如果有多个方法，那么使用 , 分隔。  ``</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// @Title Get Product list</span>
<span class="token comment">// @Description 开发时间 编写人 Get Product list by some info</span>
<span class="token comment">// @Success 200 {object} models.ZDTProduct.ProductList</span>
<span class="token comment">// @Param   category_id     query   int false       &quot;category id&quot;</span>
<span class="token comment">// @Param   brand_id    query   int false       &quot;brand id&quot;</span>
<span class="token comment">// @Param   query   query   string  false       &quot;query of search&quot;</span>
<span class="token comment">// @Param   segment query   string  false       &quot;segment&quot;</span>
<span class="token comment">// @Param   sort    query   string  false       &quot;sort option&quot;</span>
<span class="token comment">// @Param   dir     query   string  false       &quot;direction asc or desc&quot;</span>
<span class="token comment">// @Param   offset  query   int     false       &quot;offset&quot;</span>
<span class="token comment">// @Param   limit   query   int     false       &quot;count limit&quot;</span>
<span class="token comment">// @Param   price           query   float       false       &quot;price&quot;</span>
<span class="token comment">// @Param   special_price   query   bool        false       &quot;whether this is special price&quot;</span>
<span class="token comment">// @Param   size            query   string      false       &quot;size filter&quot;</span>
<span class="token comment">// @Param   color           query   string      false       &quot;color filter&quot;</span>
<span class="token comment">// @Param   format          query   bool        false       &quot;choose return format&quot;</span>
<span class="token comment">// @Failure 400 no enough input</span>
<span class="token comment">// @Failure 500 get products common error</span>
<span class="token comment">// @router /products [get]</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><h3 id="_2-4-代码逻辑注释"><a href="#_2-4-代码逻辑注释" class="header-anchor">#</a> 2.4 代码逻辑注释</h3> <blockquote><p>对于一些关键位置的代码逻辑，或者局部较为复杂的逻辑，需要有相应的逻辑说明，方便其他开发者阅读该段代码，实例如下：</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;database/sql&quot;</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token comment">//执行driver.go文件中的init(),向&quot;database/sql&quot;注册一个mysql的驱动</span>
	<span class="token boolean">_</span> <span class="token string">&quot;github.com/go-sql-driver/mysql&quot;</span> 
<span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	dsn <span class="token operator">:=</span> <span class="token string">&quot;root:admin@tcp(127.0.0.1:3306)/go_test?charset=utf8&quot;</span>
	<span class="token comment">//Open打开一个driverName指定的数据库，dataSourceName指定数据源</span>
	<span class="token comment">//不会校验用户名和密码是否正确，只会对dsn的格式进行检测</span>
	db<span class="token punctuation">,</span> err <span class="token operator">:=</span> sql<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">&quot;mysql&quot;</span><span class="token punctuation">,</span> dsn<span class="token punctuation">)</span>
	<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> <span class="token comment">//dsn格式不正确的时候会报错</span>
		fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;打开数据库失败,err:%v\n&quot;</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
		<span class="token keyword">return</span>
	<span class="token punctuation">}</span>
	<span class="token comment">//尝试连接数据库，Ping方法可检查数据源名称是否合法,账号密码是否正确。</span>
	err <span class="token operator">=</span> db<span class="token punctuation">.</span><span class="token function">Ping</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
		fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;连接数据库失败,err:%v\n&quot;</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
		<span class="token keyword">return</span>
	<span class="token punctuation">}</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;连接数据库成功！&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><h3 id="_2-5-bug注释"><a href="#_2-5-bug注释" class="header-anchor">#</a> 2.5 bug注释</h3> <blockquote><p>针对代码中出现的<code>bug</code>，可以使用特殊的注释，在<code>godocs</code>可以做到注释高亮：</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// BUG(astaxie):This divides by zero. </span>
<span class="token keyword">var</span> i float <span class="token operator">=</span> <span class="token number">1</span><span class="token operator">/</span><span class="token number">0</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h3 id="_2-6-注释风格"><a href="#_2-6-注释风格" class="header-anchor">#</a> 2.6 注释风格</h3> <blockquote><p>统一使用中文注释,对于中英文字符之间严格使用空格分隔, 这个不仅仅是中文和英文之间,英文和中文标点之间也都要使用空格分隔,例如：</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// 从 Redis 中批量读取属性，对于没有读取到的 id ， 记录到一个数组里面，准备从 DB 中读取</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>上面 Redis 、 id 、 DB 和其他中文字符之间都是用了空格分隔。</p> <ul><li><p>建议全部使用单行注释</p></li> <li><p>和代码的规范一样，单行注释不要过长，禁止超过 120 字符。</p></li></ul> <h2 id="_3-代码风格"><a href="#_3-代码风格" class="header-anchor">#</a> 3 代码风格</h2> <h3 id="_3-1-缩进和折行"><a href="#_3-1-缩进和折行" class="header-anchor">#</a> 3.1  缩进和折行</h3> <ul><li>缩进直接使用 <code>gofmt</code>工具格式化即可（<code>gofmt</code>是使用 <code>tab</code>缩进的）；</li> <li>折行方面,一行最长不超过120个字符,超过的请使用换行展示,尽量保持格式优雅。</li></ul> <h3 id="_3-2-控制结构"><a href="#_3-2-控制结构" class="header-anchor">#</a> 3.2 控制结构</h3> <h4 id="_3-2-1-语句的结尾"><a href="#_3-2-1-语句的结尾" class="header-anchor">#</a> 3.2.1 语句的结尾</h4> <ul><li>Go语言中是不需要类似于<code>Java</code>需要冒号结尾，默认一行就是一条数据</li> <li>如果你打算将多个语句写在同一行，它们则必须使用 <code>;</code></li></ul> <h4 id="_3-2-2-括号和空格"><a href="#_3-2-2-括号和空格" class="header-anchor">#</a> 3.2.2 括号和空格</h4> <blockquote><p>括号和空格方面，也可以直接使用<code>gofmt</code>工具格式化（go 会强制左大括号不换行，换行会报语法错误），所有的运算符和操作数之间要留空格</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// 正确的方式</span>
<span class="token keyword">if</span> a <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token punctuation">{</span>

<span class="token punctuation">}</span> 

<span class="token comment">// 错误的方式</span>
<span class="token keyword">if</span> a<span class="token operator">&gt;</span><span class="token number">0</span>  <span class="token comment">// a ，0 和 &gt; 之间应该空格</span>
<span class="token punctuation">{</span>       <span class="token comment">// 左大括号不可以换行，会报语法错误</span>

<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h4 id="_3-2-3-if"><a href="#_3-2-3-if" class="header-anchor">#</a> 3.2.3 if</h4> <ul><li>条件语句不需要加上圆括号</li> <li>省略不必要的 else 语句</li> <li>可以加上合适的初始化语句</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code>result <span class="token operator">:=</span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">check</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> err <span class="token punctuation">}</span>
<span class="token comment">// 不需要 else doSomeThing(result)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="_3-2-4-for"><a href="#_3-2-4-for" class="header-anchor">#</a> 3.2.4  for</h4> <p>Golang 只有 for 一种循环结构。</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h4 id="_3-2-5-遍历"><a href="#_3-2-5-遍历" class="header-anchor">#</a> 3.2.5 遍历</h4> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">//遍历字符串</span>
<span class="token keyword">for</span> pos<span class="token punctuation">,</span> str <span class="token operator">:=</span> <span class="token keyword">range</span> <span class="token string">&quot;SONY大法好&quot;</span> <span class="token punctuation">{</span> 
	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;%q: %d\n&quot;</span><span class="token punctuation">,</span> str<span class="token punctuation">,</span> pos<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">//range可以遍历数组，切片，字典，管道和字符串。</span>
<span class="token keyword">for</span> key<span class="token punctuation">,</span> value <span class="token operator">:=</span> <span class="token keyword">range</span> oldMap <span class="token punctuation">{</span>
    <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h4 id="_3-2-6-switch"><a href="#_3-2-6-switch" class="header-anchor">#</a> 3.2.6 switch</h4> <ul><li>表达式不限制为常量或整数</li> <li><code>case</code> 可以使用逗号来列举多个条件</li> <li>无需显式<code>break</code>，但使用<code>break</code> 可以提前结束</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code>  <span class="token keyword">func</span> <span class="token function">Factory</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> value <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token punctuation">{</span>
   <span class="token keyword">var</span> object <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">switch</span> name <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token string">&quot;A&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;AA&quot;</span><span class="token punctuation">:</span>
        object <span class="token operator">=</span> <span class="token function">NewA</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">case</span> <span class="token string">&quot;B&quot;</span><span class="token punctuation">:</span>
        object <span class="token operator">=</span> <span class="token function">newB</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span> value <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
			<span class="token keyword">break</span>
			<span class="token punctuation">}</span>
        object<span class="token punctuation">.</span><span class="token function">SetValue</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> object
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h4 id="_3-2-7-类型选择"><a href="#_3-2-7-类型选择" class="header-anchor">#</a> 3.2.7 类型选择</h4> <blockquote><p>对于接口变量，可以使用<code>switch</code>来判断其实际类型，这是一个很有用的技巧:</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">ErrorWrap</span><span class="token punctuation">(</span>e <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">*</span>TraceableError <span class="token punctuation">{</span>
    <span class="token keyword">var</span> message <span class="token builtin">string</span>
    <span class="token keyword">switch</span> e <span class="token operator">:=</span> e<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">case</span> TraceableError<span class="token punctuation">:</span>
        <span class="token keyword">return</span> <span class="token operator">&amp;</span>e
    <span class="token keyword">case</span> <span class="token operator">*</span>TraceableError<span class="token punctuation">:</span>
        <span class="token keyword">return</span> e
    <span class="token keyword">case</span> <span class="token builtin">error</span><span class="token punctuation">:</span>
        message <span class="token operator">=</span> e<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">default</span><span class="token punctuation">:</span>
        message <span class="token operator">=</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">&quot;%v&quot;</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token function">ErrorNew</span><span class="token punctuation">(</span>message<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h4 id="_3-2-8-退出循环"><a href="#_3-2-8-退出循环" class="header-anchor">#</a> 3.2.8 退出循环</h4> <blockquote><p>因为<code>break</code>关键字在<code>switch</code>块中有特殊含义,因此无法直接用<code>break</code>退出循环,需要借助标签:</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
Loop<span class="token punctuation">:</span>
    <span class="token keyword">for</span> index <span class="token operator">:=</span> <span class="token number">1</span><span class="token punctuation">;</span> index <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> index<span class="token operator">++</span> <span class="token punctuation">{</span>
        <span class="token keyword">switch</span> index <span class="token operator">%</span> <span class="token number">5</span> <span class="token punctuation">{</span>
        <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span>
			<span class="token keyword">break</span> 
		<span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span>
			<span class="token keyword">break</span> Loop
		<span class="token keyword">default</span><span class="token punctuation">:</span>
		    fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;%v\n&quot;</span><span class="token punctuation">,</span> index<span class="token punctuation">)</span>
		<span class="token punctuation">}</span> 
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><h4 id="_3-2-9-select"><a href="#_3-2-9-select" class="header-anchor">#</a> 3.2.9 select</h4> <blockquote><p><code>select</code>用法类似于<code>switch</code> ，专用于轮询多个管道的读取。</p></blockquote> <h3 id="_3-3-结构体和接口"><a href="#_3-3-结构体和接口" class="header-anchor">#</a> 3.3 结构体和接口</h3> <h4 id="_3-3-1-结构体初始化"><a href="#_3-3-1-结构体初始化" class="header-anchor">#</a> 3.3.1 结构体初始化</h4> <div class="language-go line-numbers-mode"><pre class="language-go"><code>p1 <span class="token operator">:=</span> <span class="token builtin">new</span> <span class="token punctuation">(</span>MyStruct<span class="token punctuation">)</span> <span class="token comment">// type *SyncedBuffer</span>
p2 <span class="token operator">:=</span> <span class="token operator">&amp;</span>MyStruct<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// type *SyncedBuffer</span>
<span class="token keyword">var</span> s1 MyStruct <span class="token comment">// type SyncedBuffer</span>
s2 <span class="token operator">:=</span> MyStruct<span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// type SyncedBuffer</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>初始化时可以指定结构成员的初始值:</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> MyStruct1 <span class="token keyword">struct</span> <span class="token punctuation">{</span>
    Value <span class="token builtin">int</span>
<span class="token punctuation">}</span>
<span class="token keyword">type</span> MyStruct2 <span class="token keyword">struct</span> <span class="token punctuation">{</span>
    MyStruct1
ID <span class="token builtin">int</span> <span class="token punctuation">}</span>
<span class="token comment">// 直接初始化</span>
s1 <span class="token operator">:=</span> MyStruct1<span class="token punctuation">{</span>
Value<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">}</span>
<span class="token comment">// 嵌套结构</span>
s2 <span class="token operator">:=</span> MyStruct2<span class="token punctuation">{</span>
    ID<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    MyStruct1<span class="token punctuation">:</span> MyStruct1 <span class="token punctuation">{</span>
Value<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="_3-4-接收者"><a href="#_3-4-接收者" class="header-anchor">#</a> 3.4 接收者</h3> <blockquote><p>方法的接收者既可以声明成值类型，也可以声明成指针类型。调用时，<code>Golang</code>可以自动进行转换。但是需要注意的是，声明成值类型时，调用方法时传入的是调用者的拷贝， 而不是调用者本身，因此对接收者的修改将不生效。
接收者类型建议如下:</p></blockquote> <ul><li>map ， func ， chan :不要使用指针</li> <li>切片类型:如果不存在对切片的重分配，</li> <li>则不要使用指针</li> <li>如果方法会改变接收者，必须使用指针</li> <li>如果接收者结构有类似 sync.Mutex 等用于同步的成员，必须使用</li> <li>一般情况，从实用性的角度出发，建议接收者都声明成指针类型</li></ul> <h3 id="_3-5-defer"><a href="#_3-5-defer" class="header-anchor">#</a> 3.5 defer</h3> <ul><li>打开文件/连接等后需要 defer 来延时执行关闭</li> <li>慎用 defer 来处理锁</li> <li>defer 求值是实时的，因此可以在循环中使用</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token string">&quot;fmt&quot;</span>
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    word <span class="token operator">:=</span> <span class="token string">&quot;world&quot;</span>
    <span class="token keyword">defer</span> fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;%v\n&quot;</span><span class="token punctuation">,</span> word<span class="token punctuation">)</span>
    word <span class="token operator">=</span> <span class="token string">&quot;blueking&quot;</span>
    fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;hello &quot;</span><span class="token punctuation">)</span> 
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="_3-5-chan"><a href="#_3-5-chan" class="header-anchor">#</a> 3.5 chan</h3> <blockquote><p><code>Golang</code>的并发模型基于<code>CSP</code>，并发实体(<code>goroutine</code>)通过管道(<code>channel</code>)进行通信。
管道本质上是一个结构体，维护发送和队列两个队列，创建管道时使用<code>make</code> :</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code>ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>不要直接声明，这样可能会导致<code>goroutine</code>死锁:</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">var</span> ch <span class="token keyword">chan</span> <span class="token builtin">int</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h4 id="_3-5-1-单向管道"><a href="#_3-5-1-单向管道" class="header-anchor">#</a> 3.5.1 单向管道</h4> <p>管道可以机上只读和只写声明,这种用法一般用在函数声明中:</p> <ul><li>只读管道: ch &lt;-chan int</li> <li>只写管道: ch chan&lt;- int</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">handle</span><span class="token punctuation">(</span>readCh <span class="token operator">&lt;-</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> writeCh <span class="token keyword">chan</span><span class="token operator">&lt;-</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
v <span class="token operator">:=</span> <span class="token operator">&lt;-</span>readCh
writeCh <span class="token operator">&lt;-</span> <span class="token number">2</span> <span class="token operator">*</span> v
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="_3-6-goroutine"><a href="#_3-6-goroutine" class="header-anchor">#</a> 3.6 goroutine</h3> <blockquote><p><code>goroutine</code>是<code>Glolang</code>提供的一种并发模型，可以通过关键字来启动轻量级线程来执行指定的逻辑。但需要注意的是，<code>goroutine</code>并不是协程，底层实现是个线程池，一个 <code>goroutine</code> 在执行的过程中可能会跑在不同的线程和 <code>CPU</code> 上。</p></blockquote> <h4 id="_3-6-1-线程安全"><a href="#_3-6-1-线程安全" class="header-anchor">#</a> 3.6.1 线程安全</h4> <blockquote><p>因为<code>goroutine</code>是在线程池中执行，因此我们在<code>goroutine</code>中访问闭包需要考虑线程安全的问题。</p></blockquote> <h4 id="_3-6-2-once"><a href="#_3-6-2-once" class="header-anchor">#</a> 3.6.2 Once</h4> <blockquote><p><code>sync.Once</code>提供了一个线程安全的单次执行接口，常用于单例模式或者初始化的场景。</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;sync&quot;</span>
<span class="token punctuation">)</span>
<span class="token keyword">type</span> singleton <span class="token keyword">struct</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">var</span> instance <span class="token operator">*</span>singleton
<span class="token keyword">var</span> once sync<span class="token punctuation">.</span>Once
<span class="token keyword">func</span> <span class="token function">GetInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span>singleton <span class="token punctuation">{</span>
    once<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        instance <span class="token operator">=</span> <span class="token operator">&amp;</span>singleton<span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> instance
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h4 id="_3-6-3-waitgroup"><a href="#_3-6-3-waitgroup" class="header-anchor">#</a> 3.6.3 WaitGroup</h4> <blockquote><p><code>Golang</code>没有提供类似 <code>thread.join</code>等待<code>goroutine</code>结束的接口,我们可以用<code>sync.WaitGroup</code>来实现:</p> <ul><li>初始化 <code>WaitGroup</code>，加上特定的值</li> <li>激活<code>goroutine，goroutine</code>结束时记得调用<code>WaitGroup.Done()</code></li> <li>主流程执行 <code>WaitGroup.Wait()</code></li></ul></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;fmt&quot;</span>
    <span class="token string">&quot;sync&quot;</span>
<span class="token punctuation">)</span>
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup
    wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
	<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	        fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;hello &quot;</span><span class="token punctuation">)</span>
	        wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	    <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
		wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	    fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;world\n&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h4 id="_3-6-4-atomic"><a href="#_3-6-4-atomic" class="header-anchor">#</a> 3.6.4 Atomic</h4> <blockquote><p><code>goroutine</code>可以使用闭包特性访问外部变量，或者多个<code>goroutine</code>共同修改同一个变量， 很容易陷入了变量并发访问的陷阱。这个时候需要借助<code>sync.atomic</code>包提供的一系列底层内存同步原语来进行同步处理。
相比于公共变量，更推荐使用管道。</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;fmt&quot;</span>
<span class="token string">&quot;sync&quot;</span>
    <span class="token string">&quot;sync/atomic&quot;</span>
<span class="token punctuation">)</span>
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> value <span class="token builtin">int64</span>
    <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup
	wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>
    fun <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>count <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">for</span> index <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> index <span class="token operator">&lt;</span> count<span class="token punctuation">;</span> index<span class="token operator">++</span> <span class="token punctuation">{</span>
            atomic<span class="token punctuation">.</span><span class="token function">AddInt64</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>value<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>  <span class="token comment">// not value++</span>
        <span class="token punctuation">}</span>
	wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
    <span class="token keyword">go</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span>
    <span class="token keyword">go</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span>
	wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;%v\n&quot;</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><h3 id="_3-7-import-规范"><a href="#_3-7-import-规范" class="header-anchor">#</a> 3.7 import 规范</h3> <blockquote><p><code>import</code>在多行的情况下,<code>goimports</code>会自动帮你格式化,但是我们这里还是规范一下<code>import</code>的一些规范，如果你在一个文件里面引入了一个<code>package</code>,还是建议采用如下格式：</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>如果你的包引入了三种类型的包，标准库包，程序内部包，第三方包，建议采用如下方式进行组织你的包：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;encoding/json&quot;</span>  <span class="token comment">//标准包</span>
    <span class="token string">&quot;strings&quot;</span>

    <span class="token string">&quot;myproject/models&quot;</span>
    <span class="token string">&quot;myproject/controller&quot;</span>   <span class="token comment">//内部包</span>
    <span class="token string">&quot;myproject/utils&quot;</span>

    <span class="token string">&quot;github.com/astaxie/beego&quot;</span>   <span class="token comment">//第三方包</span>
    <span class="token string">&quot;github.com/go-sql-driver/mysql&quot;</span>
<span class="token punctuation">)</span>   
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>有顺序的引入包，不同的类型采用空格分离，第一种实标准库，第二是项目包，第三是第三方包。</p> <p>在项目中不要使用相对路径引入包：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// 这是不好的导入</span>
<span class="token keyword">import</span> “<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token operator">/</span>net”

<span class="token comment">// 这是正确的做法</span>
<span class="token keyword">import</span> “github<span class="token punctuation">.</span>com<span class="token operator">/</span>repo<span class="token operator">/</span>proj<span class="token operator">/</span>src<span class="token operator">/</span>net”
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>但是如果是引入本项目中的其他包，最好使用相对路径。</p> <h3 id="_3-8-错误处理"><a href="#_3-8-错误处理" class="header-anchor">#</a> 3.8 错误处理</h3> <ul><li>错误处理的原则就是不能丢弃任何有返回<code>err</code>的调用，不要使用 _ 丢弃，必须全部处理。接收到错误，要么返回<code>err</code>，或者使用<code>log</code>记录下来</li> <li>尽早<code>return</code>：一旦有错误发生，马上返回</li> <li>尽量不要使用<code>panic</code>，除非你知道你在做什么</li> <li>错误描述如果是英文必须为小写，不需要标点结尾</li> <li>采用独立的错误流进行处理</li></ul> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// 错误写法</span>
<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token comment">// error handling</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">// normal code</span>
<span class="token punctuation">}</span>

<span class="token comment">// 正确写法</span>
<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token comment">// error handling</span>
    <span class="token keyword">return</span> <span class="token comment">// or continue, etc.</span>
<span class="token punctuation">}</span>
<span class="token comment">// normal code</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="_3-9-参数传递"><a href="#_3-9-参数传递" class="header-anchor">#</a> 3.9 参数传递</h3> <ul><li>对于少量数据，不要传递指针</li> <li>对于大量数据的<code>struct</code>可以考虑使用指针</li> <li>传入参数是<code>map，slice，chan</code>不要传递指针,因为<code>map，slice，chan</code>是引用类型,不需要传递指针的指针</li></ul> <h3 id="_3-10-单元测试"><a href="#_3-10-单元测试" class="header-anchor">#</a> 3.10 单元测试</h3> <ul><li>1.单元测试代码的go文件必须以<code>_test.go</code>结尾，Go语言测试工具只认符合这个规则的文件</li> <li>2.单元测试的函数名必须以<code>Test</code>开头，是可导出公开的函数。备注：函数名最好是Test+要测试的方法函数名</li> <li>3.测试函数的签名必须接收一个指向<code>testing.T类型的指针</code>作为参数，并且该测试函数不能返回任何值</li> <li>4.<a href="%5Bhttp://lsdcloud.com/go/learn-go/30%20Go%E8%AF%AD%E8%A8%80%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95.html%5D(http://lsdcloud.com/go/learn-go/30%20Go%E8%AF%AD%E8%A8%80%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95.html)">更多参考示例</a></li></ul> <h2 id="_4-数据库规范"><a href="#_4-数据库规范" class="header-anchor">#</a> 4 数据库规范</h2> <h3 id="_4-1-总命名规范"><a href="#_4-1-总命名规范" class="header-anchor">#</a> 4.1 总命名规范</h3> <ul><li>1、不得使用数据库保留关键字,以及<code>golang/php/java</code>等常用语言的保留关键字,或者可能成为关键字的单词作为完整命名。</li> <li>2、如无特殊说明,名称必须用英文字母开头,采用有特征含义的单词或缩写,单词中间用“_”分割,且只能由英文字母、数字和下划线组成,不能用双引号包含。</li> <li>3、除数据库名称长度为1至8个字符,其余（包括表、字段、索引等）不超过30个字符,<code>Database link</code>名称也不要超过30个字符。（30并不是凭空想象出来的，而是参考了Oracle的限制）</li></ul> <h3 id="_4-2-建表规范"><a href="#_4-2-建表规范" class="header-anchor">#</a> 4.2 建表规范</h3> <h4 id="_4-2-1-表名"><a href="#_4-2-1-表名" class="header-anchor">#</a> 4.2.1 表名</h4> <blockquote><p>(建议以2-3字项目名称为前缀开头),紧跟2-5个字符(英文字母或数字,但不得全是数字)的模块名(必须),
最后跟上当前表的含义的单词(1-3个单词,用下划线连接),</p></blockquote> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code>例如：SQ_SYS_CAR,SQ是项目名称的缩写,SYS是模块名称的缩写,CAR表示当前表的具体含义。
特别强调：项目名称和模块名用简写(建议长度为2-5个字符),而表含义的名称,可简写、也可以不简写,但是都不能超过3个单词,
例如下面两个反面例子：
ABF_SUPERVISION_USER，问题：模块名称似乎比较长，建议控制在2-5个字符，缩写为 ABF_SUPV_USER; 
ABF_SYS_USER_MANAGE_ORG_ROLE，问题：除去前缀ABF_SYS_，表含义（USER_MANAGE_ORG_ROLE）超过了3个单词。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h4 id="_4-2-2-字段名"><a href="#_4-2-2-字段名" class="header-anchor">#</a> 4.2.2 字段名</h4> <ul><li>a) 表的字段数不超过50个。</li> <li>b) 类型：各表之间相同含义的字段，类型定义要完全相同（包括精度、默认值等）；</li> <li>c) 命名：
<ol><li>字段名无单词数的限制，但是名字的字符长度应该符合上面的“总命名规范”。</li> <li>字段命名及其注释，要做到清楚、无歧义。</li></ol></li></ul> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code>1 表达是与否概念的字段，必须使用is_xxx的方式命名，数据类型是unsignedtinyint
2 字段名必须使用小写字母或数字；禁止出现数字开头，禁止两个下划线中间只出现数字。数据库字段名的修改代价很大，因为无法进行预发布，所以字段名称需要慎重考虑。
3 小数类型为decimal，禁止使用float和double。
4 如果存储的字符串长度几乎相等，使用char定长字符串类型。
5 表必备三字段：id, create_time, modified_time
6 修改字段含义或对字段表示的状态追加时，需要及时更新字段注释。
7 字段允许适当冗余，以提高性能，但是必须考虑数据同步的情况。
8 合适的字符存储长度，不但节约数据库表空间、节约索引存储，更重要的是提升检索速度。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="_4-3-索引规约"><a href="#_4-3-索引规约" class="header-anchor">#</a> 4.3 索引规约</h3> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code>1 【强制】业务上具有唯一特性的字段，即使是组合字段，也必须建成唯一索引
说明：不要以为唯一索引影响了insert速度，这个速度损耗可以忽略，但提高查找速度是明显的；
另外，即使在应用层做了非常完善的校验和控制，只要没有唯一索引，根据墨菲定律，必然有脏数据产生
2 【强制】超过三个表禁止join。需要join的字段，数据类型保持绝对一致；多表关联查询时，保证被关联的字段需要有索引
说明：即使双表join也要注意表索引、SQL性能。
3.【强制】在varchar字段上建立索引时，必须指定索引长度，没必要对全字段建立索引，根据实际文本区分度决定索引长度。
说明：索引的长度与区分度是一对矛盾体，一般对字符串类型数据，长度为20的索引，区分度会高达90%以上，可以使用count(distinctleft(列名, 索引长度))/count(*)的区分度来确定。
4 【推荐】如果有orderby的场景，请注意利用索引的有序性。orderby最后的字段是组合索引的一部分，并且放在索引组合顺序的最后，避免出现file_sort的情况，影响查询性能。
说明: 正例：wherea=? andb=? orderbyc;索引：a_b_c反例：索引中有范围查找，那么索引有序性无法利用，
如：WHEREa&gt;10 ORDERBYb;索引a_b无法排序。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h3 id="_4-4-sql规约"><a href="#_4-4-sql规约" class="header-anchor">#</a> 4.4 SQL规约</h3> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code>1 【强制】不要使用count(列名)或count(常量)来替代count(*)，count(*)就是SQL92定义的标准统计行数的语法，跟数据库无关，跟NULL和非NULL无关。
说明：count(*)会统计值为NULL的行，而count(列名)不会统计此列为NULL值的行。
2.【强制】count(distinctcol)计算该列除NULL之外的不重复数量。注意count(distinct col1, col2)如果其中一列全为NULL，那么即使另一列有不同的值，也返回为0。
3.【强制】当某一列的值全是NULL时，count(col)的返回结果为0，但sum(col)的返回结果为NULL，因此使用sum()时需注意NPE问题。
正例：可以使用如下方式来避免sum的NPE问题：SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;
4.【强制】使用ISNULL()来判断是否为NULL值。注意：NULL与任何值的直接比较都为NULL。
说明：1）NULL&lt;&gt;NULL的返回结果是NULL，而不是false。2）NULL=NULL的返回结果是NULL，而不是true 3）NULL&lt;&gt;1的返回结果是NULL，而不是true
5.【强制】在代码中写分页查询逻辑时，若count为0应直接返回，避免执行后面的分页语句
6.【强制】不得使用外键与级联，一切外键概念必须在应用层解决。
说明：（概念解释）学生表中的student_id是主键，那么成绩表中的student_id则为外键。
如果更新学生表中的student_id，同时触发成绩表中的student_id更新，则为级联更新。
外键与级联更新适用于单机低并发，不适合分布式、高并发集群；级联更新是强阻塞，存在数据库更新风暴的风险；外键影响数据库的插入速度。
7.【强制】禁止使用存储过程，存储过程难以调试和扩展，更没有移植性。
8.【强制】数据订正时，删除和修改记录时，要先select，避免出现误删除，确认无误才能执行更新语句。
9.【推荐】in操作能避免则避免，若实在避免不了，需要仔细评估in后边的集合元素数量，控制在1000个之内。
10.【参考】如果有全球化需要，所有的字符存储与表示，均以utf-8编码，那么字符计数方法
说明：SELECTLENGTH(&quot;轻松工作&quot;)；返回为12  SELECTCHARACTER_LENGTH(&quot;轻松工作&quot;)；返回为4
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><h3 id="_4-5-orm规约"><a href="#_4-5-orm规约" class="header-anchor">#</a> 4.5 ORM规约</h3> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code>1.【强制】在表查询中，一律不要使用* 作为查询的字段列表，需要哪些字段必须明确写明。
说明：1）增加查询分析器解析成本。2）增减字段容易与resultMap配置不一致。
2【强制】xml配置中参数注意使用：#{}，#param# 不要使用${} 此种方式容易出现SQL注入。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h2 id="_5-项目开发规范"><a href="#_5-项目开发规范" class="header-anchor">#</a> 5 项目开发规范</h2> <h3 id="_5-1-项目目录结构"><a href="#_5-1-项目目录结构" class="header-anchor">#</a> 5.1 项目目录结构</h3> <div class="language-text line-numbers-mode"><pre class="language-text"><code>+--bin 编译后的文件
+--pkg 本项目或其他项目使用的包
项目根目录
  +--api 接口规范目录
  +--cmd
  +--swagger 自动化API文档
  +--test 该目录放的是临时的测试方法
  +--config 所有的配置文件目录
  +--internal 只在本项目使用的包
  +-- doc 说明文档（含go-bindata和mysql文件）
  +-- exec_package 可执行的打包文件（目前只有win 64bit的打包）
  +-- inits 所有需初始化的目录
  |       +-- parse 所有配置文件的初始化目录
  |       +-- init.go 用于初始化系统root用户，并注入所有service
  +-- middleware 包含的中间件目录
  |       +-- casbins 用于rbac权限的中间件的目录
  |       +-- jwts jwt中间件目录
  +-- resources 打包的前端静态资源文件
  |       +--img 静态图片 
  |       +--html  网页资源
  |       +--file 文件资源
  +-- utils 工具包目录
  +--plugin 插件，扩展码的包
  +-- web
  |       +-- db 数据库dao层目录
  |       +-- models  models 存放实体类
  |       +--service 业务逻辑
  |       +-- controller 所有分发出来的路由的目录
  |       +-- supports 提供辅助方法的目录（可以无）
  +-- main.go 入口
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><h3 id="_5-2-包管理器"><a href="#_5-2-包管理器" class="header-anchor">#</a> 5.2 包管理器</h3> <blockquote><p>统一使用<code>Go Model</code>进行包管理，对标准包，程序内部包，第三方包进行分组。 <a href="http://lsdcloud.com/go/middleware/package.htm" target="_blank" rel="noopener noreferrer">更多参考<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，</p></blockquote> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span>
    <span class="token string">&quot;encoding/json&quot;</span>         <span class="token comment">//标准包</span>
    <span class="token string">&quot;strings&quot;</span>

    <span class="token string">&quot;myproject/models&quot;</span>      <span class="token comment">//内部包</span>
    <span class="token string">&quot;myproject/utils&quot;</span>

    <span class="token string">&quot;github.com/go-sql-driver/mysql&quot;</span>    <span class="token comment">//第三方包</span>
<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>常用的<code>go mod</code>命令如下：</p> <table><thead><tr><th style="text-align:left;">go mod命令</th> <th>描述</th></tr></thead> <tbody><tr><td style="text-align:left;">go mod download</td> <td>下载依赖的module到本地cache（默认为$GOPATH/pkg/mod目录）</td></tr> <tr><td style="text-align:left;">go mod edit</td> <td>编辑go.mod文件</td></tr> <tr><td style="text-align:left;">go mod graph</td> <td>打印模块依赖图</td></tr> <tr><td style="text-align:left;">go mod init</td> <td>初始化当前文件夹, 创建go.mod文件</td></tr> <tr><td style="text-align:left;">go mod tidy</td> <td>增加缺少的module，删除无用的module</td></tr> <tr><td style="text-align:left;">go mod vendor</td> <td>将依赖复制到vendor下</td></tr> <tr><td style="text-align:left;">go mod verify</td> <td>校验依赖</td></tr> <tr><td style="text-align:left;">go mod why</td> <td>解释为什么需要依赖</td></tr></tbody></table> <h3 id="_5-3-自动格式化"><a href="#_5-3-自动格式化" class="header-anchor">#</a> 5.3 自动格式化</h3> <blockquote><p><code>gofmt(goimports)</code>大部分的格式问题可以通过<code>gofmt</code>解决,<code>gofmt</code>自动格式化代码,保证所有的go代码与官方推荐的格式保持一致，于是所有格式有关问题，都以<code>gofmt</code>的结果为准</p></blockquote> <h3 id="_5-4-常用中间件"><a href="#_5-4-常用中间件" class="header-anchor">#</a> 5.4 常用中间件</h3> <table><thead><tr><th style="text-align:left;">Middleware</th> <th>描述</th> <th>Example</th></tr></thead> <tbody><tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/jwt" target="_blank" rel="noopener noreferrer">jwt<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>检查请求的Authorization头,进行JWT检查和解析</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/jwt/_example" target="_blank" rel="noopener noreferrer">jwt_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/cors" target="_blank" rel="noopener noreferrer">cors<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>HTTP 跨域请求。</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/cors/_example" target="_blank" rel="noopener noreferrer">cors_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/secure" target="_blank" rel="noopener noreferrer">secure<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>一些快速安全实现的中间件。</td> <td><a href="https://github.com/iris-contrib/middleware/blob/master/secure/_example/main.go" target="_blank" rel="noopener noreferrer">secure_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/tollboothic" target="_blank" rel="noopener noreferrer">tollbooth<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>用于验证 HTTP 请求速率的通用中间件</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/tollbooth/_examples/limit-handler" target="_blank" rel="noopener noreferrer">tollbooth_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/cloudwatch" target="_blank" rel="noopener noreferrer">cloudwatch<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>AWS cloudwatch 指标中间件。</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/cloudwatch/_example" target="_blank" rel="noopener noreferrer">cloudwatch_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/newrelic" target="_blank" rel="noopener noreferrer">new relic<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>官方 New Relic Go Agent.</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/newrelic/_example" target="_blank" rel="noopener noreferrer">newrelic_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/prometheus" target="_blank" rel="noopener noreferrer">prometheus<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>轻松为 prometheus 检测工具创建指标端点</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/prometheus/_example" target="_blank" rel="noopener noreferrer">prometheus_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/iris-contrib/middleware/tree/master/casbin" target="_blank" rel="noopener noreferrer">casbin<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>支持各种权限模型的授权库,例如ACL,RBAC,ABAC</td> <td><a href="https://github.com/iris-contrib/middleware/tree/master/casbin/_examples" target="_blank" rel="noopener noreferrer">casbin_example<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/jinzhu/gorm" target="_blank" rel="noopener noreferrer">gorm<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>gorm能够简化操作，提高开发效率。特别是对结构体的应用</td> <td><a href="https://github.com/jinzhu/gorm" target="_blank" rel="noopener noreferrer">gorm<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/go-redis/redis" target="_blank" rel="noopener noreferrer">go-redis<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>go操作redis的中间件</td> <td><a href="https://github.com/go-redis/redis" target="_blank" rel="noopener noreferrer">go-redis<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="https://github.com/spf13/viper" target="_blank" rel="noopener noreferrer">viper<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>Viper是Go应用程序的完整配置解决方案，包括12-Factor应用程序。</td> <td><a href="https://github.com/spf13/viper" target="_blank" rel="noopener noreferrer">viper<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr> <tr><td style="text-align:left;"><a href="http://github.com/json-iterator/go" target="_blank" rel="noopener noreferrer">json-iterator<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td> <td>json-iterator是一款快且灵活的JSON解析器,同时提供Java和Go两个版本。</td> <td><a href="http://github.com/json-iterator/go" target="_blank" rel="noopener noreferrer">json-iterator<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></td></tr></tbody></table> <h2 id="_6-安全规约"><a href="#_6-安全规约" class="header-anchor">#</a> 6 安全规约</h2> <h3 id="_6-1-权限控制校验"><a href="#_6-1-权限控制校验" class="header-anchor">#</a> 6.1 权限控制校验</h3> <p>系统所有页面必须进行权限控制校验。 防止没有做水平权限校验就可随意访问、操作别人的数据，比如查看、修改别人的数据。</p> <h3 id="_6-2-数据脱敏"><a href="#_6-2-数据脱敏" class="header-anchor">#</a> 6.2 数据脱敏</h3> <p>用户敏感数据禁止直接展示，必须对展示数据脱敏。 如查看个人手机号码会显示成:158****9119，隐藏中间4位，防止隐私泄露。 身份证脱敏等等</p> <h3 id="_6-3-防止sql注入"><a href="#_6-3-防止sql注入" class="header-anchor">#</a> 6.3 防止SQL注入</h3> <p>用户输入的SQL参数严格使用参数绑定或者METADATA字段值限定，防止SQL注入， 禁止字符串拼接SQL访问数据库。</p> <h3 id="_6-4-参数有效性验证"><a href="#_6-4-参数有效性验证" class="header-anchor">#</a> 6.4 参数有效性验证</h3> <p>用户请求传入的任何参数必须做有效性验证。 忽略参数校验可能导致如下异常：</p> <ul><li>pagesize过大导致内存溢出</li> <li>恶意orderby导致数据库慢查询</li> <li>任意重定向</li> <li>SQL注入</li> <li>反序列化注入</li> <li>正则输入源串拒绝服务ReDoS</li></ul> <h3 id="_6-5-csrf安全过滤"><a href="#_6-5-csrf安全过滤" class="header-anchor">#</a> 6.5 CSRF安全过滤</h3> <p>表单、AJAX提交必须执行CSRF安全过滤。 说明：CSRF(Cross-siterequestforgery)跨站请求伪造是一类常见编程漏洞。对于存在CSRF漏洞的应用/网站，攻击者可以事先构造好URL，只要受害者用户一访问，后台便在用户不知情情况下对数据库中用户参数进行相应修改。</p> <h2 id="_7-参考资料"><a href="#_7-参考资料" class="header-anchor">#</a> 7 参考资料</h2> <p><a href="https://github.com/golang/go/wiki/CodeReviewComments" target="_blank" rel="noopener noreferrer">https://github.com/golang/go/wiki/CodeReviewComments<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <p><a href="https://golang.org/doc/effective_go.html" target="_blank" rel="noopener noreferrer">https://golang.org/doc/effective_go.html<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <p><a href="http://lsdcloud.com/go/introduction.html" target="_blank" rel="noopener noreferrer">http://lsdcloud.com/go/introduction.html <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/go/web/iris-go/mvc.html" class="prev">
        MVC包的使用
      </a></span> <span class="next"><a href="/go/middleware/go-get命令详解.html">
        go get命令详解
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----></div></div>
    <script src="/assets/js/app.1bc80adb.js" defer></script><script src="/assets/js/2.7c0608ab.js" defer></script><script src="/assets/js/88.e564cbbe.js" defer></script>
  </body>
</html>
